package com.fanml.utils;

import com.fanml.entty.constant.ConstantValue;
import org.apache.commons.io.FileUtils;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * @title: FileUtil
 * @Author fanml
 * @describe: //TODO
 * @Date: 2021/7/4 17:57
 * @Version 1.0
 */
public class FileUtil {

    private static final String suffix = "part";

    public static void splintFile(File file, int blockSize, String outDirPath) throws IOException {
        if (!file.exists()) {
            throw new FileNotFoundException(file.getPath());
        }
        if (!new File(outDirPath).exists())
            new File(outDirPath).mkdirs();
        String fileName = file.getName();

        long size = blockSize * 1024 * 1024;//MB字节
        long length = file.length();
        int count = (int) (length % size == 0 ? length / size : length / size + 1);

        int countLen = String.valueOf(count).length();
        FileInputStream fileInputStream = new FileInputStream(file);
        final FileChannel channelSource = fileInputStream.getChannel();
        FileChannel channel = null;
        FileOutputStream fileOutputStream = null;
        boolean result = false;
        for (int i = 1; i <= count; i++) {
            try {
                File filePart = new File(outDirPath, fileName + "." + String.format("%0" + countLen + "d", i) + "." + suffix);
                fileOutputStream = new FileOutputStream(filePart);
                channel = fileOutputStream.getChannel();
                channelSource.transferTo((i - 1) * size, i != count ? size : length - (i - 1 * size), channel);
                fileOutputStream.close();
            } catch (IOException e) {
                result = true;
                throw e;
            } finally {
                if (fileOutputStream != null)
                    fileOutputStream.close();
                if (channel != null)
                    channel.close();
            }
        }
        try {

        } finally {
            try {
                if (fileInputStream != null)
                    fileInputStream.close();
                if (channelSource != null)
                    channelSource.close();
                if (result) {
                    FileUtils.deleteDirectory(new File(outDirPath));
                }
            } catch (IOException e) {

            }
        }
    }


    public static void mergeFile(String sourtPath, String targetPath) throws IOException {
        File fileDirSource = new File(sourtPath);
        File fileDirTarget = new File(targetPath);
        if (fileDirSource.exists() && fileDirSource.isDirectory()) {
            if (!fileDirTarget.exists())
                fileDirTarget.mkdirs();
            File[] listFiles = fileDirSource.listFiles(f -> f.getName().endsWith(suffix));
            int length = listFiles.length;
            String suffixName = "." + String.format("%0" + String.valueOf(String.valueOf(length).length()) + "d", 1) + "." + suffix;
            String fileName = listFiles[0].getName().replaceAll(suffixName, "");
            File file = new File(targetPath, fileName);
            FileChannel channelOut = new FileOutputStream(file).getChannel();

            if (length > 0) {
                FileChannel channel;
                long start = 0;
                for (int i = 0; i < length; i++) {
                    File filePart = listFiles[i];
                    channel = new FileInputStream(filePart).getChannel();
                    channelOut.transferFrom(channel, start, filePart.length());
                    start += filePart.length();
                    channel.close();
                }

                try {

                } finally {
                    channelOut.close();
                }
            }

        }
    }


    public static void mergeDirFile(String sourtPath, String targetPath) throws IOException {
        File fileDirSource = new File(sourtPath);
        File fileDirTarget = new File(targetPath);
        if (fileDirSource.exists() && fileDirSource.isDirectory()) {
            if (!fileDirTarget.exists())
                fileDirTarget.mkdirs();
            File[] listFiles = fileDirSource.listFiles();
            List<File> list = Arrays.asList(listFiles);
            list.sort(new Comparator<File>() {
                @Override
                public int compare(File o1, File o2) {
                    return Integer.valueOf(o1.getName()) - Integer.valueOf(o2.getName());
                }
            });

            int length = listFiles.length;//文件夹个数
            String suffixName = "." + String.format("%0" + String.valueOf(String.valueOf(length).length()) + "d", 1) + "." + suffix;
            String fileName = list.get(0).listFiles()[0].getName().replaceAll(suffixName, "");
            File file = new File(targetPath, fileName);
            FileChannel channelOut = new FileOutputStream(file).getChannel();
            if (length > 0) {
                FileChannel channel;
                long start = 0;
                for (int i = 0; i < length; i++) {
                    File filePart = list.get(i).listFiles()[0];
                    channel = new FileInputStream(filePart).getChannel();
                    channelOut.transferFrom(channel, start, filePart.length());
                    start += filePart.length();
                    channel.close();
                }

                try {

                } finally {
                    channelOut.close();
                }
            }
            FileUtils.deleteDirectory(fileDirSource);

        }
    }


    public static void main(String[] args) {
        try {
            String fileName = "新建文件夹.rar";
            String md5FileName = "9d65160aa26fe25aabe2c3184d9acd44";
            File localFile = new File(ConstantValue.DOWNLOAD_FILE_PATH + md5FileName, fileName);

            FileUtil.mergeDirFile(ConstantValue.DOWNLOAD_FILE_BLOCK_PATH + md5FileName, localFile.getParent());


//            String outPath = "E:\\开发环境安装包\\1";
//            splintFile(new File("E:\\迅雷下载\\cn_windows_7_ultimate_x64_dvd_x15-66043.iso"), 20, outPath);
//            mergeFile(outPath, "E:\\开发环境安装包\\2");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
